package main

import (
	"bytes"
	"encoding/json"
	"fmt"

	"github.com/hyperledger/fabric/core/chaincode/shim"
	sc "github.com/hyperledger/fabric/protos/peer"
)

type SmartContract struct {
}

// 每日数据动态
type Dealer struct{
	DealerId   string	`json:"dealerId"`
	Name   string	`json:"name"`
	Address string	`json:"address"`
}

type DealerDeal struct{
	DealerDealId   string	`json:"dealerDealId"`
	DealerId   string	`json:"dealerId"`
	SellerId string	`json:"sellerId"`
	AntisepticTreatment  string `json:"antisepticTreatment"`
	StartingTime string `json:"startingTime"`
	EndingTime string `json:"endingTime"`
	SalePrice string `json:"salePrice"`
	SalePriceUnit string `json:"salePriceUnit"`
	Amount string `json:"amount"`
	Address string `json:"address"`
}

func (s *SmartContract) Init(APIstub shim.ChaincodeStubInterface) sc.Response {
	return shim.Success(nil)
}

func (s *SmartContract) Invoke(APIstub shim.ChaincodeStubInterface) sc.Response {

	function, args := APIstub.GetFunctionAndParameters()
	if function == "query" {
		return s.query(APIstub, args)
	}else if function == "create" {
		return s.create(APIstub, args)
	} else if function == "change" {
		return s.change(APIstub, args)
	} else if function == "delete" {
		return s.delete(APIstub, args)
	} else if function == "queryAll" {
		return s.queryAll(APIstub, args)
	} else if function == "initLedger" {
		return s.initLedger(APIstub)
	} 

	return shim.Error("Invalid Smart Contract function name.")
}

func (s *SmartContract) initLedger(APIstub shim.ChaincodeStubInterface) sc.Response {
	Dealers := []Dealer{
		Dealer{DealerId: "DEALER1", Name: "PriusA", Address: "blue"},
		Dealer{DealerId: "DEALER2", Name: "PriusB", Address: "blue"},
	}

	i := 0
	for i < len(Dealers) {
		fmt.Println("i is ", Dealers[i])
		bytes, _ := json.Marshal(Dealers[i])
		fmt.Println(bytes)
		APIstub.PutState(Dealers[i].DealerId, bytes)
		fmt.Println("Added", Dealers[i])
		i = i + 1
	}

	return shim.Success(nil)
}

func (s *SmartContract) query(APIstub shim.ChaincodeStubInterface, args []string) sc.Response {
	if len(args) != 1 {
		return shim.Error("Incorrect number of arguments. Expecting 1")
	}

	bytes, _ := APIstub.GetState(args[0])
	fmt.Println(bytes)
	return shim.Success(bytes)
}

func (s *SmartContract) create(APIstub shim.ChaincodeStubInterface, args []string) sc.Response {
	model := args[0]
	arguments := args[1:len(args)]
	switch model {
		case "dealer":
			s.createDealer(APIstub, arguments)
		case "dealerDeal":
			s.createDealerDeal(APIstub, arguments)
	}
	return shim.Success(nil)
}

func (s *SmartContract) createDealer(APIstub shim.ChaincodeStubInterface, args []string) sc.Response {

	if len(args) != 3 {
		return shim.Error("Incorrect number of arguments. Expecting 3")
	}

	var Dealer = Dealer{DealerId: args[0], Name: args[1], Address: args[2]}

	DealerAsBytes, _ := json.Marshal(Dealer)
	APIstub.PutState(args[0], DealerAsBytes)

	return shim.Success(nil)
}
func (s *SmartContract) createDealerDeal(APIstub shim.ChaincodeStubInterface, args []string) sc.Response {

	if len(args) != 10 {
		return shim.Error("Incorrect number of arguments. Expecting 10")
	}

	var DealerDeal = DealerDeal {
		DealerDealId : args[0],
		DealerId : args[1],
		SellerId : args[2],
		AntisepticTreatment : args[3],
		StartingTime : args[4],
		EndingTime : args[5],
		SalePrice : args[6],
		SalePriceUnit : args[7],
		Amount : args[8],
		Address : args[9],
	}

	DealerDealAsBytes, _ := json.Marshal(DealerDeal)
	APIstub.PutState(args[0], DealerDealAsBytes)

	return shim.Success(nil)
}
func (t *SmartContract) delete(APIstub shim.ChaincodeStubInterface, args []string) sc.Response {
	if len(args) != 1 {
		return shim.Error("Incorrect number of arguments. Expecting 1")
	}

	APIstub.DelState(args[0])
	return shim.Success(nil)
}

func (s *SmartContract) change(APIstub shim.ChaincodeStubInterface, args []string) sc.Response {
	arguments := args[1:len(args)]
	s.delete(APIstub, arguments)
	s.create(APIstub, args)
	return shim.Success(nil)
}

func (s *SmartContract) queryAll(APIstub shim.ChaincodeStubInterface, args []string) sc.Response {
	model := args[0]
	var startKey string
	var endKey string
	if (model == "dealer") {
		startKey = "DEALER0"
		endKey = "DEALER99999999999"
	} else if (model == "dealerDeal") {
		startKey = "DEALERDEAL0"
		endKey = "DEALERDEAL999999999999"
	}

	resultsIterator, err := APIstub.GetStateByRange(startKey, endKey)
	if err != nil {
		return shim.Error(err.Error())
	}
	defer resultsIterator.Close()

	// buffer is a JSON array containing QueryResults
	var buffer bytes.Buffer
	buffer.WriteString("[")

	bArrayMemberAlreadyWritten := false
	for resultsIterator.HasNext() {
		queryResponse, err := resultsIterator.Next()
		if err != nil {
			return shim.Error(err.Error())
		}
		// Add a comma before array members, suppress it for the first array member
		if bArrayMemberAlreadyWritten == true {
			buffer.WriteString(",")
		}
		buffer.WriteString("{\"Key\":")
		buffer.WriteString("\"")
		buffer.WriteString(queryResponse.Key)
		buffer.WriteString("\"")

		buffer.WriteString(", \"Record\":")
		// Record is a JSON object, so we write as-is
		buffer.WriteString(string(queryResponse.Value))
		buffer.WriteString("}")
		bArrayMemberAlreadyWritten = true
	}
	buffer.WriteString("]")

	fmt.Printf("- queryAllSellers:\n%s\n", buffer.String())

	return shim.Success(buffer.Bytes())
}

func main() {

	err := shim.Start(new(SmartContract))
	if err != nil {
		fmt.Printf("Error creating new Smart Contract: %s", err)
	}
}
